#include "mainwidget.h"
#include "./ui_mainwidget.h"
#include "sessionfriendarea.h"
#include "debug.h"
#include "selfinfowidget.h"
#include "sessiondetailwidget.h"
#include "groupsessiondetailwidget.h"
#include "addfrienddialog.h"
#include "model/datacenter.h"
#include "toast.h"
#include "forecast/ForecastManager.h"

#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QTimer>

using namespace model;

MainWidget* MainWidget::instance = nullptr;

MainWidget* MainWidget::getInstance(){
    if(instance == nullptr){
        instance = new MainWidget();
    }
    return instance;
}

MainWidget::MainWidget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::MainWidget)
{
    ui->setupUi(this);

    this->setWindowTitle("FunChat简聊");
    this->setWindowIcon(QIcon(":/resource/image/funChatLogo.png"));
    //ForecastManager::globalInstance().init();
    // 初始化主窗口
    initMainWindow();
    // 左窗口
    initLeftWindow();
    // 中间窗口
    initMidWindow();
    // 右侧窗口
    initRightWindow();
    // 初始化信号槽
    initSignalSlot();
    // 初始化websocket
    initWebsocket();

    initWeatherIcon();
}

MainWidget::~MainWidget()
{
    ScreenWidget::Instance()->deleteLater();
    delete ui;
}

void MainWidget::initMainWindow()
{
    QHBoxLayout* layout = new QHBoxLayout();
    layout->setSpacing(0); // layout内部元素之间间隔
    layout->setContentsMargins(0, 0, 0, 0);  // layout元素距离边界的距离

    this->setLayout(layout);

    windowLeft = new QWidget();
    windowMid = new QWidget();
    windowRight = new QWidget();

    windowLeft->setFixedWidth(100);
    windowMid->setFixedWidth(310);
    windowRight->setMinimumWidth(800);

    windowLeft->setStyleSheet("QWidget { background-color: rgb(143, 188, 143);}");
    windowMid->setStyleSheet("QWidget { background-color: rgb(255, 255, 224);}");
    windowRight->setStyleSheet("QWidget { background-color: rgb(238, 233, 233);}");

    layout->addWidget(windowLeft);
    layout->addWidget(windowMid);
    layout->addWidget(windowRight);
}

void MainWidget::initLeftWindow()
{
    QVBoxLayout* layout = new QVBoxLayout();
    layout->setSpacing(20);
    layout->setContentsMargins(0, 50, 0, 0);
    windowLeft->setLayout(layout);

    // 用户头像
    userAvatar = new QPushButton();
    userAvatar->setToolTip("个人信息");
    userAvatar->setFixedSize(45,45);
    userAvatar->setIconSize(QSize(30, 30));
    userAvatar->setIcon(QIcon(":/resource/image/defaultAvatar.png"));
    userAvatar->setStyleSheet("QPushButton {background-color: transparent; }");
    layout->addWidget(userAvatar, 1, Qt::AlignTop | Qt::AlignHCenter);

    // 会话标签页按钮
    sessionTabBtn = new QPushButton();
    sessionTabBtn->setToolTip("聊天会话");
    sessionTabBtn->setFixedSize(45, 45);
    sessionTabBtn->setIconSize(QSize(30, 30));
    sessionTabBtn->setIcon(QIcon(":/resource/image/session_active.png"));
    sessionTabBtn->setStyleSheet("QPushButton {background-color: transparent; }");
    layout->addWidget(sessionTabBtn, 1, Qt::AlignTop | Qt::AlignHCenter);

    // 添加好友标签页
    friendTabBtn = new QPushButton();
    friendTabBtn->setToolTip("好友列表");
    friendTabBtn->setFixedSize(45, 45);
    friendTabBtn->setIconSize(QSize(30, 30));
    friendTabBtn->setIcon(QIcon(":/resource/image/friend_inactive.png"));
    friendTabBtn->setStyleSheet("QPushButton {background-color: transparent; }");
    layout->addWidget(friendTabBtn, 1, Qt::AlignTop | Qt::AlignHCenter);

    // 好友申请页按钮
    applyTabBtn = new QPushButton();
    applyTabBtn->setToolTip("好友申请");
    applyTabBtn->setFixedSize(45, 45);
    applyTabBtn->setIconSize(QSize(30, 30));
    applyTabBtn->setIcon(QIcon(":/resource/image/apply_inactive.png"));
    applyTabBtn->setStyleSheet("QPushButton {background-color: transparent; }");
    layout->addWidget(applyTabBtn, 1, Qt::AlignTop | Qt::AlignHCenter);


    layout->addStretch(50);
    // 天气展示
    QString style = "border-radius: 4px; color: rgb(255, 255, 255);";
    label_icon = new QLabel();
    label_city = new QLabel();
    label_temperture = new QLabel();
    label_lowheigh = new QLabel();
    label_icon->setStyleSheet(style);
    label_city->setStyleSheet(style);
    label_temperture->setStyleSheet(style);
    label_lowheigh->setStyleSheet(style);
    label_icon->setFixedSize(50,25);
    label_city->setFixedSize(50,10);
    label_temperture->setFixedSize(50,10);
    label_lowheigh->setFixedSize(60,20);
    layout->addWidget(label_icon, 0, Qt::AlignTop | Qt::AlignHCenter);
    layout->addWidget(label_city, 0, Qt::AlignTop | Qt::AlignHCenter);
    layout->addWidget(label_temperture, 0, Qt::AlignTop | Qt::AlignHCenter);
    layout->addWidget(label_lowheigh, 0, Qt::AlignTop | Qt::AlignHCenter);
}

void MainWidget::initMidWindow()
{
    QGridLayout* layout = new QGridLayout();
    layout->setContentsMargins(0, 20, 0, 0);
    layout->setHorizontalSpacing(0);
    layout->setVerticalSpacing(10);
    windowMid->setLayout(layout);

    searchEdit = new QLineEdit();
    searchEdit->setFixedHeight(30);
    searchEdit->setPlaceholderText("搜索好友");
    searchEdit->setStyleSheet("QLineEdit {border-radius: 5px; background-color: rgb(226, 226, 226); padding-left: 5px;}");

    addFriendBtn = new QPushButton();
    addFriendBtn->setToolTip("添加好友");
    addFriendBtn->setFixedSize(30, 30);
    addFriendBtn->setIcon(QIcon(":/resource/image/cross.png"));
    QString style = "QPushButton { border-radius: 5px; background-color: rgb(226, 226, 226);}";
    style += "QPushButton:pressed {background-color: rgb(240, 240, 240);}";
    style += "QPushButton:hover { background-color: rgb(210, 210, 210); }";
    addFriendBtn->setStyleSheet(style);

    sessionFriendArea = new SessionFriendArea();

    QWidget* spacer1 = new QWidget();
    spacer1->setFixedWidth(10);
    QWidget* spacer2 = new QWidget();
    spacer2->setFixedWidth(10);
    QWidget* spacer3 = new QWidget();
    spacer3->setFixedWidth(10);

    layout->addWidget(spacer1, 0, 0);
    layout->addWidget(searchEdit, 0, 1);
    layout->addWidget(spacer2, 0, 2);
    layout->addWidget(addFriendBtn, 0, 3);
    layout->addWidget(spacer3, 0, 4);
    layout->addWidget(sessionFriendArea, 1, 0, 1, 5);
}

void MainWidget::initRightWindow()
{
    QVBoxLayout* vlayout = new QVBoxLayout();
    vlayout->setSpacing(0);
    vlayout->setContentsMargins(0, 0, 0, 0);
    vlayout->setAlignment(Qt::AlignTop);
    windowRight->setLayout(vlayout);

    // 标题栏
    QWidget* titleWidget = new QWidget();
    titleWidget->setFixedHeight(62);
    titleWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
    titleWidget->setObjectName("titleWidget");
    titleWidget->setStyleSheet("#titleWidget {border-bottom: 2px solid rgb(230, 230, 230); border-left: 2px solid rgb(230, 230, 230);}");
    vlayout->addWidget(titleWidget);

    QHBoxLayout* hlayout = new QHBoxLayout();
    hlayout->setSpacing(0);
    hlayout->setContentsMargins(10, 0, 10, 0);
    titleWidget->setLayout(hlayout);

    sessionTitleLabel = new QLabel();
    sessionTitleLabel->setStyleSheet("QLabel { font-size: 22px; border-left: 2px solid rgb(230, 230, 230);}");

#if TEST_UI
    sessionTitleLabel->setText("表态");
#endif
    hlayout->addWidget(sessionTitleLabel);

    extraBtn = new QPushButton();
    extraBtn->setToolTip("详细信息");
    extraBtn->setFixedSize(20, 30);
    extraBtn->setIconSize(QSize(30, 30));
    extraBtn->setIcon(QIcon(":/resource/image/more.png"));
    QString style = "QPushButton { border:none; } QPushButton:pressed{ background-color: rgb(220, 220, 220);}";
    style += "QPushButton:hover { background-color: rgb(210, 210, 210); }";
    extraBtn->setStyleSheet(style);
    hlayout->addWidget(extraBtn);

    // 消息展示区
    messageShowArea = new MessageShowArea();
    vlayout->addWidget(messageShowArea);

    // 消息编辑器
    messageEditArea = new MessageEditArea();
    vlayout->addWidget(messageEditArea, 0, Qt::AlignBottom);
}

void MainWidget::initSignalSlot()
{
    model::DataCenter* dataCenter = model::DataCenter::getInstance();

    connect(sessionTabBtn, &QPushButton::clicked, this, &MainWidget::switchTabToSession);
    connect(friendTabBtn, &QPushButton::clicked, this, &MainWidget::switchTabToFriend);
    connect(applyTabBtn, &QPushButton::clicked, this, &MainWidget::switchTabToApply);

    // 个人信息 弹窗
    connect(userAvatar, &QPushButton::clicked, this, [=](){
        SelfInfoWidget* selfInfoWidget = new SelfInfoWidget(this);
        selfInfoWidget->exec();
    });

    // 会话详情按钮
    connect(extraBtn, &QPushButton::clicked, this, [=](){
// #if TEST_GROUP_SESSION_DEFAULT
//         bool isSignalChat = false;
// #else
//         bool isSignalChat = true;
// #endif
        // 获取到当前会话详细信息, 通过会话中的 userId 属性
        ChatSessionInfo* chatSessionInfo = dataCenter->findChatSessionById(dataCenter->getCurrentChatSessionId());
        if (chatSessionInfo == nullptr) {
            LOG() << "当前会话不存在, 无法弹出会话详情对话框";
            return;
        }

        bool isSingleChat = chatSessionInfo->userId != "";

        if (isSingleChat) {
            // 单聊, 弹出这个窗口
            UserInfo* userInfo = dataCenter->findFriendById(chatSessionInfo->userId);
            if (userInfo == nullptr) {
                LOG() << "单聊会话对应的用户不存在, 无法弹出会话详情窗口";
                return;
            }
            SessionDetailWidget* sessionDetailWidget = new SessionDetailWidget(this, *userInfo);
            sessionDetailWidget->exec();
        } else {
            // 群聊, 弹出另一个窗口
            GroupSessionDetailWidget* groupSessionDetailWidget = new GroupSessionDetailWidget(this);
            groupSessionDetailWidget->exec();
        }
    });

    // 添加好友按钮 弹窗
    connect(addFriendBtn, &QPushButton::clicked, this, [=](){
        AddFriendDialog* addFriendDialog = new AddFriendDialog(this);
        addFriendDialog->exec();
    });

    // 修改搜索框内容
    connect(searchEdit, &QLineEdit::textEdited, this, [=](){
        const QString& searchKey = searchEdit->text();

        AddFriendDialog* addFriendDialog = new AddFriendDialog(this);
        addFriendDialog->setSearchKey(searchKey);
        searchEdit->setText("");// 清空文本
        addFriendDialog->exec();

    });

    // 获取个人信息
    // 提供一个具体的方法, 来获取到网络数据
    connect(dataCenter, &DataCenter::getMyselfDone, this, [=]() {
        // 从 DataCenter 中拿到响应结果的 myself, 把里面的头像取出来, 显示到界面上.
        auto myself = dataCenter->getMyself();
        userAvatar->setIcon(myself->avatar);
    });
    dataCenter->getMyselfAsync();

    /////////////////////////////////////////////
    /// 获取好友列表
    /////////////////////////////////////////////
    loadFriendList();

    // 获取会话列表
    loadSessionList();

    // 获取好友申请列表
    loadApplyList();

    /////////////////////////////////////////////
    /// 处理修改头像
    /////////////////////////////////////////////
    connect(dataCenter, &DataCenter::changeAvatarDone, this, [=]() {
        UserInfo* myself = dataCenter->getMyself();
        userAvatar->setIcon(myself->avatar);
    });

    /////////////////////////////////////////////
    /// 处理删除好友
    /////////////////////////////////////////////
    connect(dataCenter, &DataCenter::deleteFriendDone, this, [=]() {
        // 更新会话列表和好友列表
        this->updateFriendList();
        this->updateChatSessionList();
        LOG() << "删除好友完成";
    });

    connect(dataCenter, &DataCenter::clearCurrentSession, this, [=]() {
        sessionTitleLabel->setText("");
        messageShowArea->clear();
        dataCenter->setCurrentChatSessionId("");
        LOG() << "清空当前会话完成";
    });

    /////////////////////////////////////////////
    /// 处理添加好友申请
    /////////////////////////////////////////////
    connect(dataCenter, &DataCenter::addFriendApplyDone, this, [=]() {
        Toast::showMessage("好友申请已发送");
    });

    /////////////////////////////////////////////
    /// 处理添加好友申请推送数据
    /////////////////////////////////////////////
    connect(dataCenter, &DataCenter::receiveFriendApplyDone, this, [=]() {
        this->updateApplyList();
        Toast::showMessage("收到新的好友申请");
    });

    /////////////////////////////////////////////
    /// 处理同意好友申请
    /////////////////////////////////////////////
    connect(dataCenter, &DataCenter::acceptFriendApplyDone, this, [=]() {
        this->updateApplyList();
        this->updateFriendList();
        //Toast::showMessage("好友已经添加完成");
    });

    /////////////////////////////////////////////
    /// 处理拒绝好友申请
    /////////////////////////////////////////////
    connect(dataCenter, &DataCenter::rejectFriendApplyDone, this, [=]() {
        // 需要更新好友申请列表. 刚才拒绝的这一项, 是需要删除掉的.
        this->updateApplyList();
        Toast::showMessage("好友申请已经拒绝");
    });

    /////////////////////////////////////////////
    /// 处理好友申请结果的推送数据
    /////////////////////////////////////////////
    connect(dataCenter, &DataCenter::receiveFriendProcessDone, this, [=](const QString& nickname, bool agree) {
        if (agree) {
            // 同意
            this->updateFriendList();
            Toast::showMessage(nickname + " 已经同意了你的好友申请");
        } else {
            // 拒绝
            Toast::showMessage(nickname + " 已经拒绝了你的好友申请");
        }
    });

    /////////////////////////////////////////////
    /// 处理创建群聊的响应信号
    /////////////////////////////////////////////
    connect(dataCenter, &DataCenter::createGroupChatSessionDone, this, [=]() {
        Toast::showMessage("创建群聊会话请求已经发送!");
    });

    /////////////////////////////////////////////
    /// 处理创建会话的推送数据
    /////////////////////////////////////////////
    connect(dataCenter, &DataCenter::receiveSessionCreateDone, this, [=]() {
        this->updateChatSessionList();
        // 通知用户, 入群
        Toast::showMessage("您被拉入到新的会话中!");
    });

    ///
    /// 群聊名称修改通知
    ///
    connect(dataCenter, &DataCenter::modifySessionNameDone, this, [=]() {
        this->updateChatSessionList();
        this->updateRecentMessage(dataCenter->getCurrentChatSessionId());
    });

    // 添加好友入群
    connect(dataCenter, &DataCenter::addGroupChatSessionMemberDone, this, [=]() {
        Toast::showMessage("邀请好友进群消息已发送!");
    });

    // 退出群聊
    connect(dataCenter, &DataCenter::quitSessionNetDone, this, [=]() {
        this->updateChatSessionList();
        //this->updateRecentMessage(dataCenter->getCurrentChatSessionId());
    });

    // 删除群聊
    connect(dataCenter, &DataCenter::removeSessionNetDone, this, [this](const QString& name) {
        this->updateChatSessionList();
        Toast::showMessage("群主解散了群聊：" + name);
    });

    // 显示错误反馈消息
    connect(dataCenter, &DataCenter::showErrorMessage, this, [](const QString& msg){
        Toast::showMessage(msg);
    });

    // 收到消息提示音
    connect(dataCenter, &DataCenter::receiveMessageBell, this, [&](){
        m_player = new QMediaPlayer(this);
        m_audioOutput = new QAudioOutput(this);
        m_player->setAudioOutput(m_audioOutput );
        m_audioOutput->setVolume(0.5);  //调节音频音量
        m_player->setSource(QUrl("qrc:/resource/file/skype.wav"));
        m_player->play();
        // Toast::showMessage("收到新消息!");
    });


    // 更新天气预报
    QTimer* timer = new QTimer(this);
    connect(timer, &QTimer::timeout, this, &MainWidget::updateForecast);
    timer->start(5000);
}

void MainWidget::initWebsocket()
{
    DataCenter* dataCenter = DataCenter::getInstance();
    dataCenter->initWebsocket();
}

void MainWidget::initWeatherIcon()
{
    mTypeIconMap.insert("晴", ":/resource/image/weatherImages/Qing.png");
    mTypeIconMap.insert("多云", ":/resource/image/weatherImages/DuoYun.png");
    mTypeIconMap.insert("阴", ":/resource/image/weatherImages/Yin.png");
    mTypeIconMap.insert("雨", ":/resource/image/weatherImages/Yu.png");
    mTypeIconMap.insert("雪", ":/resource/image/weatherImages/Xue.png");
    mTypeIconMap.insert("沙尘暴", ":/resource/image/weatherImages/ShaChenBao.png");

    mTypeIconMap.insert("雷阵雨", ":/resource/image/weatherImages/LeiZhenYu.png");
    mTypeIconMap.insert("大雨", ":/resource/image/weatherImages/DaYu.png");
    mTypeIconMap.insert("小雨", ":/resource/image/weatherImages/XiaoYu.png");
    mTypeIconMap.insert("中雨", ":/resource/image/weatherImages/ZhongYu.png");
    mTypeIconMap.insert("阵雨", ":/resource/image/weatherImages/ZhenYu.png");
    mTypeIconMap.insert("暴雨", ":/resource/image/weatherImages/BaoYu.png");
    mTypeIconMap.insert("大暴雨", ":/resource/image/weatherImages/DaBaoYu.png");
    mTypeIconMap.insert("大到暴雨",":/resource/image/weatherImages/DaDaoBaoYu.png");
    mTypeIconMap.insert("暴雨到大暴雨",":/resource/image/weatherImages/BaoYuDaoDaBaoYu.png");
    mTypeIconMap.insert("大暴雨到大暴雨",":/resource/image/weatherImages/DaBaoYuDaoDaBaoYu.png");

    mTypeIconMap.insert("暴雪",":/resource/image/weatherImages/BaoXue.png");
    mTypeIconMap.insert("大到暴雪",":/resource/image/weatherImages/DaDaoBaoXue.png");
    mTypeIconMap.insert("大雪", ":/resource/image/weatherImages/DaXue.png");
    mTypeIconMap.insert("小雪", ":/resource/image/weatherImages/XiaoXue.png");
    mTypeIconMap.insert("中雪", ":/resource/image/weatherImages/ZhongXue.png");


    mTypeIconMap.insert("雨夹雪", ":/resource/image/weatherImages/YuJiaXue.png");
    mTypeIconMap.insert("霾", ":/resource/image/weatherImages/Mai.png");
    mTypeIconMap.insert("扬沙", ":/resource/image/weatherImages/YangSha.png");
    mTypeIconMap.insert("沙尘暴", ":/resource/image/weatherImages/ShaChenBao.png");
    mTypeIconMap.insert("特大暴雨", ":/resource/image/weatherImages/TeDaBaoYu.png");
    mTypeIconMap.insert("乌", ":/resource/image/weatherImages/Wu.png");
    mTypeIconMap.insert("小到中雨", ":/resource/image/weatherImages/XiaoDaoZhongYu.png");
    mTypeIconMap.insert("小到中雪", ":/resource/image/weatherImages/XiaoDaoZhongXue.png");
    mTypeIconMap.insert("雨夹雪", ":/resource/image/weatherImages/YuJiaXue.png");
    mTypeIconMap.insert("阵雪", ":/resource/image/weatherImages/ZhenXue.png");
}

void MainWidget::switchTabToSession()
{
    activeTab = SESSION_LIST;
    sessionTabBtn->setIcon(QIcon(":/resource/image/session_active.png"));
    friendTabBtn->setIcon(QIcon(":/resource/image/friend_inactive.png"));
    applyTabBtn->setIcon(QIcon(":/resource/image/apply_inactive.png"));

    this->loadSessionList();
}

void MainWidget::switchTabToFriend()
{
    activeTab = FRIEND_LIST;
    sessionTabBtn->setIcon(QIcon(":/resource/image/session_inactive.png"));
    friendTabBtn->setIcon(QIcon(":/resource/image/friend_active.png"));
    applyTabBtn->setIcon(QIcon(":/resource/image/apply_inactive.png"));

    this->loadFriendList();
}

void MainWidget::switchTabToApply()
{
    activeTab = APPLY_LIST;
    sessionTabBtn->setIcon(QIcon(":/resource/image/session_inactive.png"));
    friendTabBtn->setIcon(QIcon(":/resource/image/friend_inactive.png"));
    applyTabBtn->setIcon(QIcon(":/resource/image/apply_active.png"));

    this->loadApplyList();
}
// 加载会话列表
void MainWidget::loadSessionList()
{
    // 先判定会话列表数据是否在本地 (DataCenter) 中存在. 如果本地存在, 直接构造界面内容.
    // 如果本地不存在, 则从服务器获取数据.
    DataCenter* dataCenter = DataCenter::getInstance();
    if (dataCenter->getChatSessionList() != nullptr) {
        // 从内存加载数据显示
        updateChatSessionList();
    } else {
        // 从网络加载数据
        connect(dataCenter, &DataCenter::getChatSessionListDone, this, &MainWidget::updateChatSessionList, Qt::UniqueConnection);
        dataCenter->getChatSessionListAsync();
    }
}
// 加载好友
void MainWidget::loadFriendList()
{
    // 好友列表数据是在 DataCenter 中存储的
    // 首先需要判定 DataCenter 中是否已经有数据了. 如果有数据, 直接加载本地的数据.
    // 如果没有数据, 从服务器获取
    DataCenter* dataCenter = DataCenter::getInstance();
    if (dataCenter->getFriendList() != nullptr) {
        // 从内存这个列表中加载数据
        updateFriendList();
    } else {
        // 通过网络来加载数据
        connect(dataCenter, &DataCenter::getFriendListDone, this, &MainWidget::updateFriendList, Qt::UniqueConnection);
        dataCenter->getFriendListAsync();
    }
}
// 加载申请
void MainWidget::loadApplyList()
{
    // 好友申请列表在 DataCenter 中存储的
    // 首先判定 DataCenter 本地是否已经有数据了. 如果有, 直接加载到界面上.
    // 如果没有则需要从服务器获取
    DataCenter* dataCenter = DataCenter::getInstance();
    if (dataCenter->getApplyList() != nullptr) {
        // 本地有数据, 直接加载
        updateApplyList();
    } else {
        // 本地没有数据, 通过网络加载
        connect(dataCenter, &DataCenter::getApplyListDone, this, &MainWidget::updateApplyList, Qt::UniqueConnection);
        dataCenter->getApplyListAsync();
    }
}

void MainWidget::updateFriendList()
{
    if (activeTab != FRIEND_LIST) {
        // 当前的标签页不是好友列表, 就不渲染任何数据到界面上
        return;
    }
    DataCenter* dataCenter = DataCenter::getInstance();
    QList<UserInfo>* friendList = dataCenter->getFriendList();

    // 清空一下之前界面上的数据.
    sessionFriendArea->clear();

    QString userId = dataCenter->getMyself()->userId;
    // 遍历好友列表, 添加到界面上
    for (const auto& f : *friendList) {
        if(userId != f.userId)
            sessionFriendArea->addIem(FriendItemType, f.userId, f.avatar, f.nickname, f.description);
    }
}

void MainWidget::updateChatSessionList()
{
    if (activeTab != SESSION_LIST) {
        // 当前标签页不是会话列表, 不渲染任何数据到界面上
        return;
    }
    DataCenter* dataCenter = DataCenter::getInstance();
    QList<ChatSessionInfo>* chatSessionList = dataCenter->getChatSessionList();

    sessionFriendArea->clear();

    for (const auto& c : *chatSessionList) {
        if (c.lastMessage.messageType == TEXT_TYPE) {
            sessionFriendArea->addIem(SessionItemType, c.chatSessionId, c.avatar, c.chatSessionName, c.lastMessage.content, c.lastMessage.time);
        } else if (c.lastMessage.messageType == IMAGE_TYPE) {
            sessionFriendArea->addIem(SessionItemType, c.chatSessionId, c.avatar, c.chatSessionName, "[图片]", c.lastMessage.time);
        } else if (c.lastMessage.messageType == FILE_TYPE) {
            sessionFriendArea->addIem(SessionItemType, c.chatSessionId, c.avatar, c.chatSessionName, "[文件]", c.lastMessage.time);
        } else if (c.lastMessage.messageType == SPEECH_TYPE) {
            sessionFriendArea->addIem(SessionItemType, c.chatSessionId, c.avatar, c.chatSessionName, "[语音]", c.lastMessage.time);
        } else {
            LOG() << "错误的消息类型! messageType=" << c.lastMessage.messageType;
        }
    }
}

void MainWidget::updateApplyList()
{
    if (activeTab != APPLY_LIST) {
        // 当前标签页不是 "好友申请列表", 界面上不做任何渲染
        return;
    }
    DataCenter* dataCenter = DataCenter::getInstance();
    QList<UserInfo>* applyList = dataCenter->getApplyList();

    sessionFriendArea->clear();

    for (const auto& u : *applyList) {
        // 直接把这个 UserInfo 对象添加到界面上即可, 不涉及到 PB 和 自己的结构之间的转换.
        // 此处 UserInfo 的 description 不需要填写进来. 好友申请列表中, 不显示用户的签名的 (这个位置被替换成了两个按钮)
        sessionFriendArea->addIem(ApplyItemType, u.userId, u.avatar, u.nickname, "");
    }
}

void MainWidget::updateForecast()
{
    ForecastManager& manager = ForecastManager::globalInstance();
    m_Today = manager.getWeatherInfo();

    label_city->setText(m_Today->city);
    label_lowheigh->setText(QString(m_Today->low + "℃ ~ " + m_Today->high + "℃"));
    label_temperture->setText(m_Today->wendu + "℃");
    QString imageUrl = mTypeIconMap[m_Today->type];
    if (imageUrl.isEmpty()) imageUrl = ":/resource/image/weatherImages/undefined.png";
    label_icon->setPixmap(imageUrl);

}

void MainWidget::loadRecentMessage(const QString &chatSessionId)
{
    // 也是先判定, 本地内存中是否已经有对应的消息列表数据.
    // 有的话直接显示到界面上. 没有的话从网络获取.
    DataCenter* dataCenter = DataCenter::getInstance();

    if (dataCenter->getRecentMessageList(chatSessionId) != nullptr) {
        // 拿着本地数据更新界面
        updateRecentMessage(chatSessionId);
    } else {
        // 本地没有数据, 从网络加载
        connect(dataCenter, &DataCenter::getRecentMessageListDone, this, &MainWidget::updateRecentMessage, Qt::UniqueConnection);
        dataCenter->getRecentMessageListAsync(chatSessionId, true);
    }
}

void MainWidget::updateRecentMessage(const QString &chatSessionId)
{
    // 1. 拿到该会话的最近消息列表
    DataCenter* dataCenter = DataCenter::getInstance();
    auto* recentMessageList = dataCenter->getRecentMessageList(chatSessionId);

    // 2. 清空原有界面上显示的消息列表
    messageShowArea->clear();

    // 3. 根据当前拿到的消息列表, 显示到界面上
    //    此处把数据显示到界面上, 可以使用头插, 也可以使用尾插.
    //    这里打算使用头插的方式来进行实现.
    //    主要因为消息列表来说, 用户首先看到的, 应该是 "最近" 的消息, 也就是 "末尾" 的消息.
    for (int i = recentMessageList->size() - 1; i >= 0; --i) {
        const Message& message = recentMessageList->at(i);
        bool isLeft = message.sender.userId != dataCenter->getMyself()->userId;
        messageShowArea->addFrontMessage(isLeft, message);
    }

    // 4. 设置会话标题
    ChatSessionInfo* chatSessionInfo = dataCenter->findChatSessionById(chatSessionId);
    if (chatSessionInfo != nullptr) {
        // 把会话名称显示到界面上.
        sessionTitleLabel->setText(chatSessionInfo->chatSessionName);
    }

    // 5. 保存当前选中的会话是哪个.
    dataCenter->setCurrentChatSessionId(chatSessionId);

    // 6. 自动把滚动条, 滚动到末尾
    messageShowArea->scrollToEnd();
}

void MainWidget::switchSession(const QString &userId)
{
    // 1. 在会话列表中, 先找到对应的会话元素
    DataCenter* dataCenter = DataCenter::getInstance();
    ChatSessionInfo* chatSessionInfo = dataCenter->findChatSessionByUserId(userId);
    if (chatSessionInfo == nullptr) {
        // 正常来说, 每个好友, 都会有一个对应的会话(哪怕从来没说过话).
        // 添加好友的时候, 就创建出来的会话.
        LOG() << "[严重错误] 当前选中的好友, 对应的会话不存在!";
        return;
    }

    // 2. 把选中的会话置顶, 把这个会话信息放到整个会话列表的第一个位置.
    //    后续在界面显示的时候, 就是按照列表的顺序, 从前往后显示的.
    dataCenter->topChatSessionInfo(*chatSessionInfo);

    // 3. 切换到会话列表标签页
    switchTabToSession();

    // 4. 加载这个会话对应的历史消息. 刚刚做了一个 "置顶操作" , 被选中的好友对应的会话, 在会话列表的最前头, 也就是 0 号下标.
    sessionFriendArea->clickItem(0);
}

MessageShowArea *MainWidget::getMessageShowArea()
{
    return messageShowArea;
}

void MainWidget::initCityCode()
{
    // 读取文件
    QFile file(":/citycode.json");
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        // 处理文件打开失败的情况
        return;
    }
    QByteArray json = file.readAll();
    file.close();
        // 解析json，并且写入到map，这个文件是json数组
    QJsonParseError error;
    QJsonDocument doc = QJsonDocument::fromJson(json, &error);
    if (error.error != QJsonParseError::NoError || !doc.isArray())
    {
        // 处理JSON解析失败的情况
        return;
    }
    // 然后获取json数据当中的城市名字和对应的编码
    QJsonArray cityArr = doc.array();
    for (int i = 0; i < cityArr.size(); i++)
    {
        QString city = cityArr[i].toObject().value("city_name").toString();
        QString code = cityArr[i].toObject().value("city_code").toString();
            // 然后写入到map
        // 注意当输入是省份时，是没有城市编码的，不可以查整个省份的天气，只能是具体的城市
        if (!code.isEmpty())
        {
            mCityMap.insert(city, code);
        }
    }
}

QString MainWidget::getCityCode(QString cityName)
{
    // 初始化map
    if (mCityMap.isEmpty())
    {
        initCityCode();
    }
    // 根据城市名字遍历map，获取城市编码
    QMap<QString, QString>::iterator it = mCityMap.find(cityName);
    // 特殊：输入北京/北京市都可以找到
    if (it == mCityMap.end())
    {
        it = mCityMap.find(cityName + "市");
    }
    if (it == mCityMap.end())
    {
        it = mCityMap.find(cityName + "区");
    }
    if (it == mCityMap.end())
    {
        it = mCityMap.find(cityName + "县");
    }
    // 如果遍历到有这个城市名字，就返回编码
    if (it != mCityMap.end())
    {
        return it.value();
    }
    return ""; // 没有就返回空
}





















